import { Component, OnInit, OnDestroy, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { CodeDataService } from '../../services/code-data.service';
import { MonacoEditorService } from '../../services/monaco-editor.service';
import { SyntaxHighlightService } from '../../services/syntax-highlight.service';
import { CodeViewerData, CodeRegion, ProcessedLine, LineVisibility, LineType } from '../../models/code-content.interface';

interface DisplayLine {
  lineNumber: number;
  content: string;
  highlightedContent?: string; // 新增：高亮后的HTML内容
  isCollapsedPlaceholder?: boolean;
  hiddenLineStart?: number;
  hiddenLineEnd?: number;
  regionBefore?: string;
  regionAfter?: string;
  lineType?: LineType;
  backgroundColor?: string;
}

@Component({
  selector: 'app-code-viewer',
  standalone: true,
  imports: [CommonModule, RouterModule],
  templateUrl: './code-viewer.component.html',
  styleUrls: ['./code-viewer.component.scss']
})
export class CodeViewerComponent implements OnInit, OnDestroy, AfterViewInit {
  @ViewChild('editorContainer', { static: false }) editorContainer!: ElementRef<HTMLDivElement>;

  codeData: CodeViewerData | null = null;
  loading = true;
  error: string | null = null;
  editor: any = null;
  processedLines: ProcessedLine[] = [];
  displayLines: DisplayLine[] = [];
  expandedRegions: Set<string> = new Set();
  
  // Monaco Editor 相关状态
  useMonacoEditor = true; // 默认使用Monaco Editor
  monacoLoading = false;
  monacoError: string | null = null;

  constructor(
    private codeDataService: CodeDataService,
    private monacoService: MonacoEditorService,
    private syntaxHighlightService: SyntaxHighlightService,
    private sanitizer: DomSanitizer
  ) {}

  ngOnInit(): void {
    this.loadCodeData();
  }

  ngAfterViewInit(): void {
    this.initializeEditor();
  }

  ngOnDestroy(): void {
    this.destroyMonacoEditor();
  }

  private async loadCodeData(): Promise<void> {
    try {
      this.codeDataService.getCodeData().subscribe({
        next: (data) => {
          this.codeData = data;
          this.processCodeContent();
          this.loading = false;
          
          // 如果编辑器已经初始化，更新内容
          if (this.editor) {
            this.updateEditorContent();
          }
        },
        error: (error) => {
          console.error('加载代码数据失败:', error);
          this.error = '加载代码数据失败，请稍后重试';
          this.loading = false;
        }
      });
    } catch (error) {
      console.error('请求代码数据时发生错误:', error);
      this.error = '请求数据时发生错误';
      this.loading = false;
    }
  }

  private async initializeEditor(): Promise<void> {
    try {
      await this.monacoService.loadMonacoEditor();
      
      if (this.editorContainer) {
        this.editor = this.monacoService.createEditor(this.editorContainer.nativeElement, {
          theme: 'vs',
          language: this.codeData?.fileContent.language || 'typescript',
          readOnly: true,
          automaticLayout: true,
          minimap: { enabled: false },
          scrollBeyondLastLine: false,
          lineNumbers: 'on',
          fontSize: 14,
          wordWrap: 'on',
          renderLineHighlight: 'none',
          glyphMargin: true,
          lineNumbersMinChars: 4
        });

        // 如果数据已加载，更新编辑器内容
        if (this.codeData) {
          this.updateEditorContent();
        }
      }
    } catch (error) {
      console.error('初始化编辑器失败:', error);
      this.error = '编辑器初始化失败';
    }
  }

  private processCodeContent(): void {
    if (!this.codeData) return;

    const lines = this.codeData.fileContent.content.split('\n');
    this.processedLines = [];
    this.displayLines = [];

    // 创建行状态映射
    const lineVisibilityMap = new Map<number, { 
      visibility: LineVisibility; 
      regionId?: string; 
      lineType: LineType;
      backgroundColor?: string;
    }>();

    // 标记原始可见区域
    this.codeData.visibleRegions.forEach((region, index) => {
      for (let i = region.startLine; i <= region.endLine; i++) {
        lineVisibilityMap.set(i, {
          visibility: LineVisibility.VISIBLE,
          regionId: region.id || `region-${index}`,
          lineType: LineType.ORIGINAL_VISIBLE,
          backgroundColor: region.backgroundColor
        });
      }
    });

    // 处理每一行
    lines.forEach((content, index) => {
      const lineNumber = index + 1;
      const lineInfo = lineVisibilityMap.get(lineNumber);

      this.processedLines.push({
        lineNumber,
        content,
        visibility: lineInfo?.visibility || LineVisibility.HIDDEN,
        lineType: lineInfo?.lineType,
        regionId: lineInfo?.regionId,
        backgroundColor: lineInfo?.backgroundColor
      });
    });

    // 生成显示行数组
    this.generateDisplayLines();
  }

  private generateDisplayLines(): void {
    this.displayLines = [];
    let i = 0;

    while (i < this.processedLines.length) {
      const line = this.processedLines[i];
      
      if (line.visibility === LineVisibility.VISIBLE) {
        // 可见行直接添加，并应用语法高亮
        const highlightedContent = this.syntaxHighlightService.highlightCode(
          line.content, 
          this.codeData?.fileContent.language || 'typescript'
        );

        this.displayLines.push({
          lineNumber: line.lineNumber,
          content: line.content,
          highlightedContent: highlightedContent,
          lineType: line.lineType,
          backgroundColor: line.backgroundColor
        });
        i++;
      } else {
        // 找到连续的隐藏行区域
        const hiddenStart = i;
        while (i < this.processedLines.length && this.processedLines[i].visibility === LineVisibility.HIDDEN) {
          i++;
        }
        const hiddenEnd = i - 1;
        const hiddenCount = hiddenEnd - hiddenStart + 1;
        
        // 添加折叠占位符
        this.displayLines.push({
          lineNumber: this.processedLines[hiddenStart].lineNumber,
          content: `// ··· ${hiddenCount} 行被折叠 ···`,
          isCollapsedPlaceholder: true,
          hiddenLineStart: this.processedLines[hiddenStart].lineNumber,
          hiddenLineEnd: this.processedLines[hiddenEnd].lineNumber,
          regionBefore: hiddenStart > 0 ? this.processedLines[hiddenStart - 1].regionId : undefined,
          regionAfter: hiddenEnd < this.processedLines.length - 1 ? this.processedLines[hiddenEnd + 1].regionId : undefined
        });
      }
    }
  }

  private updateEditorContent(): void {
    if (!this.editor || !this.codeData) return;

    // 生成显示的代码内容
    const displayContent = this.displayLines.map(line => line.content).join('\n');
    
    this.monacoService.setEditorContent(
      this.editor,
      displayContent,
      this.codeData.fileContent.language
    );

    // 设置自定义行号
    this.setupCustomLineNumbers();
  }

  private setupCustomLineNumbers(): void {
    if (!this.editor) return;

    // 自定义行号显示
    const monaco = (window as any).monaco;
    if (!monaco) return;
    
    this.editor.updateOptions({
      lineNumbers: (lineNumber: number) => {
        const displayLine = this.displayLines[lineNumber - 1];
        if (displayLine) {
          if (displayLine.isCollapsedPlaceholder) {
            return `${displayLine.hiddenLineStart}-${displayLine.hiddenLineEnd}`;
          }
          return displayLine.lineNumber.toString();
        }
        return lineNumber.toString();
      }
    });
  }

  // 展开指定区域 - 采用“就地修改”策略，不再重新生成整个列表
  expandRegion(startLine: number, endLine: number, placeholderIndex: number): void {
    if (!this.codeData || placeholderIndex < 0 || placeholderIndex >= this.displayLines.length) {
      return;
    }

    // 1. 从processedLines中获取要展开的新行
    const newLines: DisplayLine[] = [];
    for (let i = startLine - 1; i < endLine; i++) {
      if (i < this.processedLines.length) {
        const line = this.processedLines[i];
        const highlightedContent = this.syntaxHighlightService.highlightCode(
          line.content,
          this.codeData.fileContent.language
        );
        newLines.push({
          lineNumber: line.lineNumber,
          content: line.content,
          highlightedContent: highlightedContent,
          lineType: LineType.MANUALLY_EXPANDED, // 标记为手动展开
          backgroundColor: undefined // 手动展开的行没有特殊背景色
        });
        // 更新processedLines中的状态，以便canExpand等函数能够正确工作
        line.visibility = LineVisibility.VISIBLE;
        line.lineType = LineType.MANUALLY_EXPANDED;
      }
    }

    // 2. 更新displayLines：用新行替换占位符
    if (newLines.length > 0) {
      this.displayLines.splice(placeholderIndex, 1, ...newLines);
    } else {
      // 如果没有新行可以展开（比如已经到了文件末尾），直接移除占位符
      this.displayLines.splice(placeholderIndex, 1);
    }
    
    // 3. 如果使用的是Monaco Editor，则需要更新其内容（虽然不推荐，但保持功能兼容）
    if (this.useMonacoEditor && this.editor) {
      this.updateEditorContent();
    }
  }

  // 展开隐藏区域（从折叠占位符调用）
  expandHiddenRegion(startLine: number, endLine: number, placeholderIndex: number): void {
    const linesToExpand = this.processedLines.slice(startLine - 1, endLine);
    
    // 更新processedLines中的可见性
    linesToExpand.forEach(line => {
        line.visibility = LineVisibility.VISIBLE;
        line.lineType = LineType.MANUALLY_EXPANDED;
        line.backgroundColor = undefined;
    });

    const newDisplayLines = linesToExpand.map(line => {
        const highlightedContent = this.syntaxHighlightService.highlightCode(line.content, this.codeData!.fileContent.language);
        return {
            lineNumber: line.lineNumber,
            content: line.content,
            highlightedContent: highlightedContent,
            lineType: LineType.MANUALLY_EXPANDED
        };
    });

    // 找到占位符并替换
    if (placeholderIndex > -1 && placeholderIndex < this.displayLines.length) {
        // 检查占位符周围是否还有隐藏行，以决定是否需要创建新的占位符
        const placeholder = this.displayLines[placeholderIndex];
        const originalHiddenStart = placeholder.hiddenLineStart!;
        const originalHiddenEnd = placeholder.hiddenLineEnd!;

        // 替换操作
        this.displayLines.splice(placeholderIndex, 1, ...newDisplayLines);

        // 检查上方是否需要新的占位符
        if (originalHiddenStart < startLine) {
            const newPlaceholder: DisplayLine = {
                lineNumber: originalHiddenStart,
                content: `// ··· ${startLine - originalHiddenStart} 行被折叠 ···`,
                isCollapsedPlaceholder: true,
                hiddenLineStart: originalHiddenStart,
                hiddenLineEnd: startLine - 1,
            };
            this.displayLines.splice(placeholderIndex, 0, newPlaceholder);
        }

        // 检查下方是否需要新的占位符
        if (originalHiddenEnd > endLine) {
            const newPlaceholder: DisplayLine = {
                lineNumber: endLine + 1,
                content: `// ··· ${originalHiddenEnd - endLine} 行被折叠 ···`,
                isCollapsedPlaceholder: true,
                hiddenLineStart: endLine + 1,
                hiddenLineEnd: originalHiddenEnd,
            };
            // 因为上方可能已经插入了一个占位符，所以插入位置需要调整
            const insertionIndex = placeholderIndex + newDisplayLines.length + (originalHiddenStart < startLine ? 1 : 0);
            this.displayLines.splice(insertionIndex, 0, newPlaceholder);
        }
    }
    
    // 如果是Monaco模式，则更新
    if (this.useMonacoEditor && this.editor) {
        this.updateEditorContent();
    }
  }


  // 向上展开5行 - 从结束行向上展开
  expandUpward(startLine: number, endLine: number, placeholderIndex: number): void {
    const expandCount = 5;
    const expandEnd = endLine;
    const expandStart = Math.max(startLine, endLine - expandCount + 1);
    
    if (expandEnd >= expandStart) {
      this.expandHiddenRegion(expandStart, expandEnd, placeholderIndex);
    }
  }

  // 向下展开5行 - 从起始行向下展开
  expandDownward(startLine: number, endLine: number, placeholderIndex: number): void {
    const expandCount = 5;
    const expandStart = startLine;
    const expandEnd = Math.min(endLine, startLine + expandCount - 1);
    
    if (expandEnd >= expandStart) {
      this.expandHiddenRegion(expandStart, expandEnd, placeholderIndex);
    }
  }

  // 展开指定区域上方的隐藏行（改为使用5行增量）
  expandAbove(regionId: string): void {
    const region = this.codeData?.visibleRegions.find(r => r.id === regionId);
    if (!region) return;

    // 找到该区域前面的5行隐藏行
    const expandCount = 5;
    const startLine = Math.max(1, region.startLine - expandCount);
    this.expandRegion(startLine, region.startLine - 1, this.displayLines.findIndex(line => line.isCollapsedPlaceholder && line.hiddenLineStart === startLine));
  }

  // 展开指定区域下方的隐藏行（改为使用5行增量）
  expandBelow(regionId: string): void {
    const region = this.codeData?.visibleRegions.find(r => r.id === regionId);
    if (!region || !this.codeData) return;

    // 找到该区域后面的5行隐藏行
    const expandCount = 5;
    const endLine = Math.min(this.codeData.fileContent.totalLines, region.endLine + expandCount);
    this.expandRegion(region.endLine + 1, endLine, this.displayLines.findIndex(line => line.isCollapsedPlaceholder && line.hiddenLineStart === (region.endLine + 1)));
  }

  // 获取可见区域信息
  getVisibleRegions(): CodeRegion[] {
    return this.codeData?.visibleRegions || [];
  }

  // 重新加载数据
  reloadData(): void {
    this.loading = true;
    this.error = null;
    this.loadCodeData();
  }

  // 获取文件信息
  getFileInfo(): string {
    if (!this.codeData) return '';
    return `${this.codeData.fileContent.filename} (${this.codeData.fileContent.totalLines} 行)`;
  }

  // 获取显示行数组（用于模板）
  getDisplayLines(): DisplayLine[] {
    return this.displayLines;
  }

  // 展开所有隐藏行
  expandAll(): void {
    // 将所有隐藏行设置为可见，标记为手动展开
    this.processedLines.forEach(line => {
      if (line.visibility === LineVisibility.HIDDEN) {
        line.visibility = LineVisibility.VISIBLE;
        line.lineType = LineType.MANUALLY_EXPANDED;
        // 手动展开的行不设置背景色
        line.backgroundColor = undefined;
      }
    });

    // 重新生成显示行和编辑器内容
    this.generateDisplayLines();
    this.updateEditorContent();
  }

  // 重置显示（折叠所有额外展开的行）
  collapseAll(): void {
    if (!this.codeData) return;

    // 重新处理代码内容，恢复到初始状态
    this.processCodeContent();
    this.updateEditorContent();
  }

  // 检查是否支持语法高亮
  isSyntaxHighlightSupported(): boolean {
    if (!this.codeData) return false;
    return this.syntaxHighlightService.isSupportedLanguage(this.codeData.fileContent.language);
  }

  /**
   * 安全地处理高亮后的HTML内容
   */
  getSafeHtml(content: string): SafeHtml {
    return this.sanitizer.bypassSecurityTrustHtml(content);
  }

  /**
   * 切换Monaco Editor模式
   */
  async toggleMonacoEditor(): Promise<void> {
    this.useMonacoEditor = !this.useMonacoEditor;
    
    if (this.useMonacoEditor) {
      await this.initializeMonacoEditor();
    } else {
      this.destroyMonacoEditor();
    }
  }

  /**
   * 初始化Monaco Editor
   */
  private async initializeMonacoEditor(): Promise<void> {
    if (!this.codeData) return;

    this.monacoLoading = true;
    this.monacoError = null;

    try {
      // 加载Monaco Editor
      await this.monacoService.loadMonacoEditor();
      
      // 等待DOM更新
      setTimeout(() => {
        this.createMonacoEditor();
      }, 100);
    } catch (error) {
      console.error('Monaco Editor初始化失败:', error);
      this.monacoError = 'Monaco Editor加载失败';
      this.useMonacoEditor = false;
    } finally {
      this.monacoLoading = false;
    }
  }

  /**
   * 创建Monaco Editor实例
   */
  private createMonacoEditor(): void {
    if (!this.editorContainer?.nativeElement || !this.codeData) return;

    try {
      // 销毁现有编辑器
      this.destroyMonacoEditor();

      // 准备完整的代码内容
      const fullContent = this.codeData.fileContent.content;
      const language = this.codeData.fileContent.language;

      // 创建新的编辑器
      this.editor = this.monacoService.createEditor(this.editorContainer.nativeElement, {
        value: fullContent,
        language: language,
        readOnly: true,
        theme: 'vs-light'
      });

      // 高亮显示可见区域
      this.highlightVisibleRegionsInMonaco();

      console.log('Monaco Editor创建成功');
    } catch (error) {
      console.error('创建Monaco Editor失败:', error);
      this.monacoError = '编辑器创建失败';
      this.useMonacoEditor = false;
    }
  }

  /**
   * 在Monaco Editor中高亮可见区域
   */
  private highlightVisibleRegionsInMonaco(): void {
    if (!this.editor || !this.codeData) return;

    // 高亮所有可见区域
    this.codeData.visibleRegions.forEach(region => {
      this.monacoService.highlightLines(
        this.editor, 
        region.startLine, 
        region.endLine, 
        'highlighted-line'
      );
    });

    // 滚动到第一个可见区域
    if (this.codeData.visibleRegions.length > 0) {
      const firstRegion = this.codeData.visibleRegions[0];
      this.monacoService.revealLines(this.editor, firstRegion.startLine, firstRegion.endLine);
    }
  }

  /**
   * 销毁Monaco Editor
   */
  private destroyMonacoEditor(): void {
    if (this.editor) {
      this.monacoService.destroyEditor(this.editor);
      this.editor = null;
    }
  }

  /**
   * 检查Monaco Editor是否已加载
   */
  isMonacoLoaded(): boolean {
    return this.monacoService.isLoaded();
  }

  // 获取当前语言
  getCurrentLanguage(): string {
    return this.codeData?.fileContent.language || 'typescript';
  }
} 